package ui;

import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.FlatteningPathIterator;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;

public class ZigZagStroke implements Stroke
{
	private float				amplitude	= 8.0f;
	private float				wavelength	= 7.0f;
	private Stroke				stroke;
	private static final float	FLATNESS	= 1;

	public ZigZagStroke(Stroke stroke, float amplitude, float wavelength)
	{
		this.stroke = stroke;
		this.amplitude = amplitude;
		this.wavelength = wavelength;
	}

	public Shape createStrokedShape(Shape shape)
	{
		GeneralPath result = new GeneralPath();
		PathIterator it = new FlatteningPathIterator(
				shape.getPathIterator(null), FLATNESS);
		float points[] = new float[6];
		float moveX = 0, moveY = 0;
		float lastX = 0, lastY = 0;
		float thisX = 0, thisY = 0;
		int type = 0;
		boolean first = false;
		float next = 0;
		int phase = 0;

		float factor = 1;

		while (!it.isDone())
		{
			type = it.currentSegment(points);
			switch (type)
			{
			case PathIterator.SEG_MOVETO:
				moveX = lastX = points[0];
				moveY = lastY = points[1];
				result.moveTo(moveX, moveY);
				first = true;
				next = wavelength / 2;
				break;

			case PathIterator.SEG_CLOSE:
				points[0] = moveX;
				points[1] = moveY;
				// Fall into....

			case PathIterator.SEG_LINETO:
				thisX = points[0];
				thisY = points[1];
				float dx = thisX - lastX;
				float dy = thisY - lastY;
				float distance = (float) Math.sqrt(dx * dx + dy * dy);
				if (distance >= next)
				{
					float r = 1.0f / distance;
					float angle = (float) Math.atan2(dy, dx);
					while (distance >= next)
					{
						float x = lastX + next * dx * r;
						float y = lastY + next * dy * r;
						float tx = amplitude * dy * r;
						float ty = amplitude * dx * r;
						if (( phase & 1 ) == 0)
							result.lineTo(x + amplitude * dy * r, y - amplitude
									* dx * r);
						else
							result.lineTo(x - amplitude * dy * r, y + amplitude
									* dx * r);
						next += wavelength;
						phase++;
					}
				}
				next -= distance;
				first = false;
				lastX = thisX;
				lastY = thisY;
				if (type == PathIterator.SEG_CLOSE)
					result.closePath();
				break;
			}
			it.next();
		}

		return stroke.createStrokedShape(result);
	}

}
